//
//  AtModel.swift
//  Tinsecret_TW
//
//  Created by 崔世强 on 2018/10/30.
//  Copyright © 2018 tst. All rights reserved.
//

import Foundation

class AtModel<T:Hashable> {
    var atBlocks = [T:AtBlock]()
    
    func reset() {
        atBlocks.removeAll()
    }
    
    func addAtMember(key:T,name:String,start:Int) ->AtSegment {
        guard let atBlock = atBlocks[key] else {
            let atBlock = AtBlock(text:name)
            atBlocks[key] = atBlock
            let segment = atBlock.addSegment(start: start)
            return segment
        }
        return atBlock.addSegment(start: start)
    }
    
    func addAtMember(key:T,name:String,start:Int) ->AtBlock {
        guard let atBlock = atBlocks[key] else {
            let atBlock = AtBlock(text:name)
            atBlocks[key] = atBlock
            _ = atBlock.addSegment(start: start)
            return atBlock
        }
        _ = atBlock.addSegment(start: start)
        return atBlock
    }
    
    func getAllMember() -> [T]{
        return atBlocks.filter{$1.valid()}.map{ (key,block) -> T in
            return key
        }
    }
    
    func getAtBlock(key:T) -> AtBlock? {
        return atBlocks[key]
    }
    
    func findAtSegmentByEndPosition(start:Int) -> AtSegment? {
        for (_,block) in atBlocks {
            if let segment = block.findLastSegmentByEnd(end: start) {
                return segment
            }
        }
        return nil
    }
    
    func onInsertText(start:Int,changeText:String) {
        var iterator = atBlocks.makeIterator()
        while let (key,block) = iterator.next() {
            block.moveRight(start: start, length: changeText.count)
            if !block.valid() {
                self.atBlocks.removeValue(forKey: key)
            }
        }
    }
    
    func onTextChange(range:NSRange,changeText:String) {
        let start = range.location
        let length = range.length
        let changeLength = changeText.count - length
        
        if changeLength > 0 {
            moveRight(start: start, length: changeLength)
        } else if changeLength < 0 {
            moveLeft(start: start, length: -changeLength)
        }
    }
    
    func moveRight(start:Int,length:Int) {
        for (key,block) in atBlocks {
            block.moveRight(start: start, length: length)
            if !block.valid() {
                self.atBlocks.removeValue(forKey: key)
            }
        }
    }
    func moveLeft(start:Int,length:Int) {
        for (key,block) in atBlocks {
            block.moveLeft(start: start, length: length)
            if !block.valid() {
                self.atBlocks.removeValue(forKey: key)
            }
        }
    }
    
    func onDeleteText(start:Int,length:Int) {
        var iterator = atBlocks.makeIterator()
        while let (key,block) = iterator.next(){
            block.moveLeft(start: start, length: length)
            if !block.valid() {
                self.atBlocks.removeValue(forKey: key)
            }
        }
    }
}
